/* *
*代理模式是一种为其他对象提供一种代理以控制对该对象的访问的设计模式。在代理模式中，代理对象充当着客户端和真实对象之间的中介，它可以对客户端的请求进行过滤、验证、记录、缓存等操作，最后再交给真实对象处理。

*在前端开发中，代理模式经常用于优化性能、降低服务器负载等方面，以下是一些代理模式的应用场景：

*1. 虚拟代理：用于图片等资源的加载，在请求资源之前，先使用一个代理对象来展示一张占位图，当真实的资源加载完成后，再替换掉占位图。

*2. 缓存代理：用于缓存数据，通常用于需要执行耗时操作的函数，当函数的参数相同时，直接返回缓存中的结果，避免重复计算。

*3. 保护代理：用于控制访问权限，限制对对象的访问，常用于安全性较高的场合。

*另外，在一些框架和库中，代理模式也经常被使用，例如 React 和 Vue 中的虚拟 DOM 和计算属性等，都是使用代理模式来实现的。
* */
//? 真正需要执行的对象
class RealSubject {
    request() {
        console.log('RealSubject: Handling request.');
    }
}
//? 定义一个代理对象
class ProxySubject {
    constructor(realSubject) {
        this.realSubject = realSubject;
    }
    request() {
        //? 在真实对象处理请求之前执行一些操作
        console.log('ProxySubject: Logging request.');
        //? 调用真实对象的方法
        this.realSubject.request();
    }
}
//? 使用代理对象处理请求
const realSubject = new RealSubject();
const proxySubject = new ProxySubject(realSubject);
proxySubject.request();  // 输出：ProxySubject: Logging request. RealSubject: Handling request.

//? 提到代理模式，一定会想到 Proxy 这玩意
//? Proxy  是 ES6 中新增的一个对象，它可以用来创建一个代理对象，同时也是代理模式的一种实现方式。
//? 使用  Proxy  对象可以拦截并重定义 JavaScript 语言的底层操作，例如属性访问、函数调用、构造函数调用等等。这使得我们可以对对象的行为进行修改和控制

const target = {
    name: 'Alice'
};
const handler = {
    get(target, prop) {
        console.log(`Getting ${prop}`);
        return target[prop];
    },
    set(target, prop, value) {
        console.log(`Setting ${prop}=${value}`);
        target[prop] = value;
    }
};
const proxy = new Proxy(target, handler);
console.log(proxy.name); //? 实际上调用了get方法，get方法在返回值前会做一些操作 输出：Getting name Alice
proxy.age = 20; //? set同理 输出：Setting age=20
console.log(target); //? 输出：{name: "Alice", age: 20}
